home *** CD-ROM | disk | FTP | other *** search
- /*
- * inode.c
- *
- * Stuff for translating (dev,inode) pairs to file names
- *
- * Stolen from memusage programs
- *
- * Copyright 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/param.h>
-
- #include <stdio.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "process.h"
- #include "draw.h"
-
- #define INODEFILE ".gmemusage.inodes"
- #define INODEFILETMP ".gmemusage.inodes.tmp"
- #define DEFUSAGEPATH \
- "/usr/ToolTalk:/usr/bin:/usr/lib:/usr/local:/usr/Cadmin:"\
- "/usr/CaseVision:/usr/sbin:/usr/bsd:/usr/etc:/lib:"\
- "/sbin:/bin:/etc:/usr/gfx "
- #define PATHSEP ";,: "
- #define FINDCMD "find "
- #define FINDARGS "-type f \\( -perm -0100 -o -name \\*so\\* \\) -print "
- #define FINDMUNGE " | xargs /sbin/ls -lLid | " \
- "sed -e /fonts/d -e /terminfo/d | " \
- "awk '{printf \"%d %s\\n\", $1, $10 }' "\
- ";"\
- "echo "\
- "/dev/zero "\
- "| xargs /sbin/ls -lLid | "\
- "awk '{printf \"%d %s\\n\", $1, $11 }'"
-
-
- struct inrec {
- struct inrec *next;
- long inode;
- dev_t rdev;
- char *name;
- };
-
- static struct inrec *inodes;
- static char *inodePath = NULL;
- static char *inodePathTmp = NULL;
-
- static void
- MakePaths(void)
- {
- char *home;
-
- if (!inodePath) {
- home = getenv("HOME");
- if (!home) {
- home = "/var/tmp";
- }
- /*
- * 2 == 1 ('/') + 1 ('\0')
- */
- inodePath = malloc(strlen(home) + strlen(INODEFILE) + 2);
- sprintf(inodePath, "%s/%s", home, INODEFILE);
- inodePathTmp = malloc(strlen(home) + strlen(INODEFILETMP) + 2);
- sprintf(inodePathTmp, "%s/%s", home, INODEFILETMP);
- }
- }
-
- /*
- * static char *
- * basename(char *path)
- *
- * Description:
- * Get the base file name of a path. Local so I don't have to
- * suck in libgen just for this one trivial fuction.
- *
- * Parameters:
- * path
- *
- * Returns:
- * Pointer to basename of path (not duplicated!)
- */
-
- static char *
- basename(char *path)
- {
- char *slash;
-
- slash = strrchr(path, '/');
-
- return slash ? slash + 1 : path;
- }
-
- static dev_t
- easy_stat (char *path)
- {
- struct stat statbuf;
- if (stat (path, &statbuf) != 0)
- return -1;
- return statbuf.st_dev;
- }
-
- static dev_t
- get_device (char *path)
- {
- struct stat st;
- char buff[MAXPATHLEN + 12], str[MAXPATHLEN], buf[256];
- FILE *fp;
-
- dev_t i;
- if ((i = easy_stat(path)) > 0)
- return i;
-
- sprintf (buff, "/etc/devnm %s", path, getpid());
-
- if ((fp = popen(buff, "r")) == NULL) {
- perror("popen");
- return -1;
- }
- setbuffer(fp, buf, sizeof buf);
-
- fscanf (fp, "%s", str);
- pclose (fp);
-
- if (strcmp (str, "devnm:") == 0) {
- return (-1);
- }
- if (strncmp (str, "/dev/", 5) != 0 &&
- strchr (str, ':') == NULL) {
- strcpy (buff, "/dev/");
- } else {
- strcpy (buff, "");
- }
- strcat (buff, str);
-
- if (lstat (buff, &st) == 0 &&
- (st.st_mode & S_IFMT) == S_IFBLK) {
- return (st.st_rdev);
- } else {
- perror ("get_device: lstat");
- return (-1);
- }
- }
-
- /*
- * static int
- * BuildInodeTable(void)
- *
- * Description:
- * Find a whole bunch of files, and get their inode numbers
- *
- * Returns:
- * 0 if successful, -1 if error
- */
-
- static int
- BuildInodeTable(void)
- {
- dev_t ndev;
- FILE *fp, *inodefp;
- long inode;
- char str[256], *findCmd, *usagePath, *dir;
- char buf1[BUFSIZ], buf2[BUFSIZ];
- pid_t pid;
- int errfd;
-
- /*
- * use usagePath as the path to look for executables
- */
- usagePath = getenv("USAGEPATH");
-
- if (!usagePath) {
- usagePath = DEFUSAGEPATH;
- }
-
- /*
- * Dup it because strtok is going to modify it
- */
- usagePath = strdup(usagePath);
-
- findCmd = malloc(strlen(usagePath) + strlen(FINDCMD)
- + strlen(FINDARGS) + strlen(FINDMUNGE) + 1);
-
- strcpy(findCmd, FINDCMD);
-
- for (dir = strtok(usagePath, PATHSEP); dir;
- dir = strtok(NULL, PATHSEP)) {
- strcat(findCmd, dir);
- strcat(findCmd, " ");
- }
-
- strcat(findCmd, FINDARGS);
- strcat(findCmd, FINDMUNGE);
-
- /*
- * Save our stderr for after the find command, and redirect stderr
- * to /dev/null while running find. This is so that the user
- * doesn't see find's error messages when it can't find things in
- * our list.
- */
- errfd = dup(2);
- close(2);
- (void)open("/dev/null", O_WRONLY);
-
- if ((fp = popen(findCmd, "r")) == NULL) {
- dup2(errfd, 2);
- close(errfd);
- perror("popen");
- return -1;
- }
- setbuffer(fp, buf1, sizeof buf1);
-
- /*
- * Swap euid and uid, so we don't create any files that someone
- * with our uid couldn't create.
- */
- (void)setreuid(geteuid(), getuid());
-
- if ((inodefp = fopen(inodePathTmp, "w")) == NULL) {
- pclose(fp);
- dup2(errfd, 2);
- close(errfd);
- (void)setreuid(geteuid(), getuid());
- perror("fopen");
- return -1;
- }
- setbuffer(fp, buf2, sizeof buf2);
-
- while (fscanf (fp, "%d %s\n", &inode, str) == 2) {
- ndev = get_device (str);
- fprintf (inodefp, "%d %d %s\n", ndev, inode, str);
- }
-
- pclose (fp);
- fclose(inodefp);
-
- /*
- * Restore stderr
- */
- dup2(errfd, 2);
- close(errfd);
-
- /*
- * We don't create the actual database unless all has gone well.
- */
- (void)unlink(inodePath);
- if (link(inodePathTmp, inodePath) == -1) {
- perror("link");
- }
- if (unlink(inodePathTmp) == -1) {
- perror("unlink");
- }
-
- /*
- * Swap back so that we can open everything in /proc
- */
- (void)setreuid(geteuid(), getuid());
- return 0;
- }
-
- /*
- * static void
- * add_inode(long inode, dev_t rdev, char *str)
- *
- * Description:
- * Add an inode to the internal list
- *
- * Parameters:
- * inode inode to add
- * rdev dev to add
- * str name to add
- */
-
- static void
- add_inode(long inode, dev_t rdev, char *str)
- {
- struct inrec *new;
-
- new = (struct inrec *)malloc(sizeof (struct inrec));
- new->next = inodes;
- new->inode = inode;
- new->rdev = rdev;
- new->name = strdup(str);
- /*
- * Be careful! InodeLookup relies on the fact that the new
- * inode goes at the head of the list; if you change this,
- * make sure to fix InodeLookup.
- */
- inodes = new;
- }
-
- /*
- * Add dynamic paths into dev/ino map list
- */
- static void
- prdynpaths(void)
- {
- static char *paths[] = { "/var/tmp/.Xshmtrans0",
- "/tmp/.cadminOSSharedArena",
- NULL };
- register int i;
- struct stat statd;
-
- /* Add elements to the list */
- for (i = 0; paths[i] != NULL; ++i) {
- if (stat(paths[i], &statd) < 0)
- continue;
- add_inode (statd.st_dev, statd.st_ino, paths[i]);
- }
- }
-
- /*
- * int
- * InodeInit(void)
- *
- * Description:
- * Initialize inode table. If it exists and is newer than /unix,
- * read it in. Otherwise, create it.
- *
- * Returns:
- * 0 if successful, -1 if error
- */
-
- int
- InodeInit(void)
- {
- struct stat stunix, stinodes;
- char str[MAXPATHLEN], buffer[BUFSIZ];
- int rdev, inode;
- FILE *fp;
-
- MakePaths();
-
- if (stat("/unix", &stunix) == -1) {
- perror("/unix");
- return -1;
- }
-
- if (stat(inodePath, &stinodes) == -1 ||
- stunix.st_mtime > stinodes.st_mtime) {
- WaitMessage("Building inode database. This will take a while,",
- "but only has to be done once.");
- if (BuildInodeTable() == -1) {
- return -1;
- }
- }
-
- if ((fp = fopen(inodePath, "r")) == NULL) {
- perror("fopen");
- return -1;
- }
- setbuffer(fp, buffer, sizeof buffer);
-
- while (fscanf(fp,"%d %d %s\n",&rdev,&inode,str) == 3) {
- add_inode (inode, rdev, basename(str));
- }
-
- fclose(fp);
- prdynpaths();
- return 0;
- }
-
- /*
- * Given a vnode at address vloc, find a corresponding path name
- */
- char *
- InodeLookup(int rdev, int inode)
- {
- struct inrec *current;
- FILE *fp;
- static char buf[100];
-
- for (current = inodes; current; current = current->next)
- if (current->inode == inode && current->rdev == rdev)
- return current->name;
-
- sprintf(buf, "#%d", inode);
- add_inode(inode, rdev, buf);
- return inodes->name; /* rely on side effect of add_indode */
- }
-
- /*
- * int
- * FindInode(char *str, dev_t *rdev, ino_t *ino)
- *
- * Description:
- * Given a string, find the inode and device number
- *
- * Parameters:
- * str string to find device and inode of
- * rdev gets device
- * ino gets inode
- *
- * Returns:
- * 0 if successful, -1 if error
- */
-
- int
- FindInode(char *str, dev_t *rdev, ino_t *ino)
- {
- struct inrec *current;
-
- for (current = inodes; current; current = current->next)
- if (strcmp(current->name, str) == NULL) {
- if (rdev) *rdev = current->rdev;
- if (ino) *ino = current->inode;
- return 0;
- }
- return -1;
- }
-
- int
- InvalidateInodeTable(void)
- {
- MakePaths();
- (void)unlink(inodePath);
- (void)unlink(inodePathTmp);
- }
-